/*
 * To change this template, choose Tools | Templates
 * and open the template in the editor.
 */
package ucmconfchecker.UI;

import java.util.*;
import ucmconfchecker.conformance.*;
import ucmconfchecker.pArchitecture.Architecture;
import ucmconfchecker.pImplementation.*;

/**
 *
 * @author Administrador
 */
public class  ApplicationModel<T,G> {
    
    private Architecture<T,G> architecture;    
    private Map<String,Scenario<T>> scenarios;
    private Map<String,EventTrace<T>> eventTraces;
    private Collection<EClass> implementation;
    
    private Collection<T> universe;
    private Map<Scenario<T>,EventTraceGroup<T>> tracesForScenarios;
    
    
    private boolean _precedence = true;
    private boolean _missingEvent = true;
    private boolean _missingPrecondition = true;
    private boolean _unexpectedEvent = true;
    
    private Map<Scenario<T>,HashMap<EventTrace<T>,Report<T>>> reports;
    private boolean _strict;
    
    public void setArchitecture(Architecture<T,G> architecture){
        this.architecture=architecture;
    }
    public void addScenario(Scenario<T> scenario){
        if(scenarios==null){
           scenarios = new HashMap<String,Scenario<T>>(); 
        }
        scenarios.put(scenario.getName(),scenario);
    }
    public Scenario<T> getScenario(String name){
        if(scenarios!=null) {
            return scenarios.get(name);
        }else {
            return null;
        }
    }
    public Map<String,Scenario<T>> getScenarios(){
        return scenarios;
    }
    
    public Report<T> getReport(Scenario<T> scenario, EventTrace<T> trace){
        if(getReports()!=null){
            Map<EventTrace<T>,Report<T>> scenarioReports = getReports().get(scenario);
            if(scenarioReports!=null && scenarioReports.containsKey(trace)){
                return scenarioReports.get(trace);
            }
        }
        return null;
    }
    public Report<T> getReport(Scenario<T> scenario){
        Map<EventTrace<T>,Report<T>> scenarioReports = getReports().get(scenario);
        if(scenarioReports!=null){
            return Report.merge(scenarioReports.values());
        }
        return null;
    }
    public Report<T> getConsolidatedReport(){
        if(getReports()!=null && !getReports().keySet().isEmpty()){
            
            List<Report<T>> scenarioReports = new ArrayList<Report<T>>();
            for(Scenario<T> scenario: getReports().keySet()){
                scenarioReports.add(getReport(scenario));
            }
            return Report.merge(scenarioReports);
        }
        return null;
    }
    public void check(){
        if(getUniverse() == null){
            setUniverse(getArchitecture().getResponsibilities());
        }
        ConformanceChecker checker = new ConformanceChecker(getUniverse());
        checker.setMissingEvent(_missingEvent);
        checker.setMissingPrecondition(_missingPrecondition);
        checker.setPrecedence(_precedence);
        checker.setStrictPrecedence(_strict);
        checker.setUnexpectedEvent(_unexpectedEvent);
        if(scenarios!=null){
            for(Scenario<T> scenario: scenarios.values()){
                for(EventTrace<T> trace: getEventTraces().values()){
                    if(getReports()==null){
                        setReports(new HashMap<Scenario<T>,HashMap<EventTrace<T>,Report<T>>>());
                    }if(getReports().get(scenario)==null){
                        getReports().put(scenario, new HashMap<EventTrace<T>,Report<T>>());
                    }
                    getReports().get(scenario).put(trace,checker.check(scenario, trace));
                }
            }
        }
    }
    
    public boolean isPrecedence() {
        return _precedence;
    }

    public void setPrecedence(boolean precedence) {
        this._precedence = precedence;
    }

    public boolean isMissingEvent() {
        return _missingEvent;
    }

    public void setMissingEvent(boolean missinEvent) {
        this._missingEvent = missinEvent;
    }

    public boolean isMissingPrecondition() {
        return _missingPrecondition;
    }

    public void setMissingPrecondition(boolean missingPrecondition) {
        this._missingPrecondition = missingPrecondition;
    }

    public boolean isUnexpectedEvent() {
        return _unexpectedEvent;
    }

    public void setUnexpectedEvent(boolean unexpectedEvent) {
        this._unexpectedEvent = unexpectedEvent;
    }
    public Architecture<T,G> getArchitecture() {
        return architecture;
    }
    
    public Map<String,EventTrace<T>> getEventTraces() {
        return eventTraces;
    }
    public EventTrace<T> getEventTrace(String name) {
        if(eventTraces!=null){
            return eventTraces.get(name);
        }else{
            return null;
        }
    }
    public void addEventTrace(EventTrace<T> eventTrace) {
        if(this.eventTraces==null){
             this.eventTraces = new HashMap<String,EventTrace<T>>();
        }
        this.eventTraces.put(eventTrace.getName(),eventTrace);
    }

    public Collection<EClass> getImplementation() {
        return implementation;
    }

    public void setImplementation(Collection<EClass> implementation) {
        this.implementation = implementation;
          for(EClass eClass : implementation){
              System.out.println("Class:"+eClass.getName());
              System.out.println("Class:"+eClass.getClassName()+" package: "+eClass.getPackage());
              if(eClass.getMethods()!=null){
                  for(EMethod method: eClass.getMethods()){
                      System.out.println("+ Method:"+method.getName());
                  }
              }
              
          }
    }

    public Collection<T> getUniverse() {
        return universe;
    }

    public void setUniverse(Collection<T> universe) {
        this.universe = universe;
    }

    public Map<Scenario<T>,EventTraceGroup<T>> getTracesForScenarios() {
        return tracesForScenarios;
    }

     public void setTracesForScenarios(Map<Scenario<T>,EventTraceGroup<T>> tracesForScenarios) {
        this.tracesForScenarios = tracesForScenarios;
    }

    public Map<Scenario<T>,HashMap<EventTrace<T>,Report<T>>> getReports() {
        return reports;
    }

    public void setReports(Map<Scenario<T>,HashMap<EventTrace<T>,Report<T>>> reports) {
        this.reports = reports;
    }

    void setStrictPrecedence(boolean selected) {
        this._strict = selected;
    }
    
}
